<template>
  <div class="role-manage-container">
    <!-- 页面标题 + 操作栏 -->
    <div class="page-header">
      <h2 class="page-title">角色管理</h2>
      <div class="operation-bar">
        <el-input
            v-model="searchValue"
            placeholder="请输入角色名称或角色编码搜索"
            class="search-input"
            clearable
            @keyup.enter="handleSearch"
            style="width: 300px; height: 40px;"
        >
          <template #append>
            <el-button :icon="Search" @click="handleSearch" style="height: 100%; border-left: none;" />
          </template>
        </el-input>
        <el-button
            type="primary"
            @click="showAddDialog = true"
            icon="el-icon-plus"
            style="height: 40px;"
        >
          添加角色
        </el-button>
      </div>
    </div>

    <!-- 角色表格 -->
    <el-card class="table-card">
      <el-skeleton v-if="loading" row-count="5" :columns="6" border></el-skeleton>

      <el-table
          v-else
          :data="filteredRoleList"
          style="width: 100%"
          stripe
          border
          :header-cell-style="{ background: '#f5f7fa', color: '#333', fontWeight: 500 }"
          :cell-style="{ color: '#666' }"
          @row-click="handleRowClick"
      >
        <el-table-column prop="roleId" label="角色 ID" width="100" align="center"></el-table-column>
        <el-table-column prop="roleName" label="角色名称" width="160" align="center"></el-table-column>
        <el-table-column prop="roleCode" label="角色编码" width="180" align="center"></el-table-column>
        <el-table-column label="已关联菜单数" width="160" align="center">
          <template #default="{ row }">
            <span>{{ row.menuCount || 0 }} 个</span>
          </template>
        </el-table-column>
        <el-table-column min-width="200" label="操作" align="center">
          <template #default="{ row }">
            <el-button
                type="text"
                color="#409eff"
                size="small"
                @click.stop="editRole(row)"
            >
              编辑
            </el-button>
            <el-button
                type="text"
                color="#f56c6c"
                size="small"
                @click.stop="handleDeleteConfirm(row.roleId)"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <div v-if="!loading && filteredRoleList.length === 0" class="empty-tip">
        <el-empty description="暂无角色数据"></el-empty>
      </div>
    </el-card>

    <!-- 编辑角色对话框 -->
    <el-dialog
        v-model="showEditDialog"
        title="编辑角色（分配菜单权限）"
        width="650px"
        :close-on-click-modal="false"
        @open="handleEditDialogOpen"
    >
      <el-form
          :model="editRoleInfo"
          label-width="100px"
          class="role-form"
          :rules="editRoleRules"
          ref="editRoleFormRef"
          style="margin-top: 10px;"
      >
        <!-- 角色基本信息 -->
        <el-form-item label="角色 ID" disabled>
          <el-input v-model="editRoleInfo.roleId" style="width: 100%;"></el-input>
        </el-form-item>
        <el-form-item label="角色名称" prop="roleName">
          <el-input
              v-model="editRoleInfo.roleName"
              placeholder="请输入角色名称（最多128字）"
              maxlength="128"
              style="width: 100%;"
          ></el-input>
        </el-form-item>
        <el-form-item label="角色编码" prop="roleCode">
          <el-input
              v-model="editRoleInfo.roleCode"
              placeholder="请输入角色编码（如：ADMIN）"
              maxlength="128"
              style="width: 100%;"
          ></el-input>
        </el-form-item>

        <!-- 菜单权限分配区域 -->
        <el-form-item label="菜单权限" prop="selectedMenuIds">
          <div class="menu-tree-container">
            <el-skeleton v-if="menuLoading" style="height: 300px;" border></el-skeleton>

            <!-- 树形菜单（核心修复部分） -->
            <el-tree ref="menuTreeRef" 
            v-else
            :data="allMenus"
            :props="treeProps"
            :show-checkbox="true"
            :default-checked-keys="selectedMenuIds"
            :check-strictly="false"
            :node-key="treeNodeKey"
            @check="handleMenuCheck"
            style="max-height: 300px; overflow-y: auto;"
            ></el-tree>
          </div>
          <div class="menu-tip">
            <i class="el-icon-info" style="color: #409eff; margin-right: 5px;"></i>
            勾选父菜单将自动获取其所有子菜单权限，取消父菜单将取消所有子菜单权限
          </div>
        </el-form-item>
      </el-form>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="showEditDialog = false">取消</el-button>
          <el-button type="primary" @click="updateRoleWithMenu">确定保存</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 添加角色对话框 -->
    <el-dialog
        v-model="showAddDialog"
        title="添加角色"
        width="500px"
        :close-on-click-modal="false"
        @open="handleAddDialogOpen"
    >
      <el-form
          :model="addRoleInfo"
          label-width="100px"
          class="role-form"
          :rules="addRoleRules"
          ref="addRoleFormRef"
      >
        <el-form-item label="角色名称" prop="roleName">
          <el-input
              v-model="addRoleInfo.roleName"
              placeholder="请输入角色名称"
              maxlength="128"
          ></el-input>
        </el-form-item>
        <el-form-item label="角色编码" prop="roleCode">
          <el-input
              v-model="addRoleInfo.roleCode"
              placeholder="请输入角色编码"
              maxlength="128"
          ></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showAddDialog = false">取消</el-button>
        <el-button type="primary" @click="addRole">确定添加</el-button>
      </template>
    </el-dialog>

    <!-- 删除确认对话框 -->
    <el-dialog
        v-model="showDeleteDialog"
        title="删除确认"
        width="300px"
        :close-on-click-modal="false"
    >
      <p>确定要删除该角色吗？删除后不可恢复。</p>
      <template #footer>
        <el-button @click="showDeleteDialog = false">取消</el-button>
        <el-button type="danger" @click="deleteRole">确定删除</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, reactive } from 'vue';
import {ElMessage, ElTree, ElForm, ElButton} from 'element-plus';
import httpRequest from "@/config/request";
import {Search} from "@element-plus/icons-vue";

// 角色列表相关状态
const roleList = ref([]);
const filteredRoleList = ref([]);
const loading = ref(false);
const searchValue = ref('');

// 对话框状态
const showAddDialog = ref(false);
const showEditDialog = ref(false);
const showDeleteDialog = ref(false);
const deleteRoleId = ref('');

// 表单引用
const editRoleFormRef = ref(null);
const addRoleFormRef = ref(null);

// 菜单权限相关状态
const allMenus = ref([]);
const menuLoading = ref(false);
const selectedMenuIds = ref([]);
const menuTreeRef = ref(null);  // 树形菜单引用

// 树形菜单配置
const treeNodeKey = 'menuId';
const treeProps = reactive({
  label: 'name',
  children: 'children',
  disabled: 'hidden'
});

// 编辑角色表单数据
const editRoleInfo = reactive({
  roleId: '',
  roleName: '',
  roleCode: '',
  selectedMenuIds: []  // 用于表单验证的选中菜单ID
});

// 添加角色表单数据
const addRoleInfo = reactive({
  roleName: '',
  roleCode: ''
});

// 表单验证规则
const editRoleRules = reactive({
  roleName: [
    { required: true, message: '请输入角色名称', trigger: 'blur' },
    { max: 128, message: '角色名称最多128个字符', trigger: 'blur' }
  ],
  roleCode: [
    { required: true, message: '请输入角色编码', trigger: 'blur' },
    { pattern: /^[A-Za-z0-9_]+$/, message: '角色编码仅支持字母、数字和下划线', trigger: 'blur' }
  ],
  selectedMenuIds: [
    { required: true, message: '请至少选择一个菜单', trigger: ['change', 'blur'] },
    { type: 'array', min: 1, message: '请至少选择一个菜单', trigger: ['change', 'blur'] }
  ]
});

const addRoleRules = reactive({
  roleName: [
    { required: true, message: '请输入角色名称', trigger: 'blur' },
    { max: 128, message: '角色名称最多128个字符', trigger: 'blur' }
  ],
  roleCode: [
    { required: true, message: '请输入角色编码', trigger: 'blur' },
    { pattern: /^[A-Za-z0-9_]+$/, message: '角色编码仅支持字母、数字和下划线', trigger: 'blur' }
  ]
});

// 格式化菜单数据：确保children始终为数组
const formatMenuData = (menus) => {
  if (!Array.isArray(menus)) return [];
  return menus.map(menu => ({
    ...menu,
    children: formatMenuData(menu.children || [])
  }));
};

// 编辑对话框打开时加载数据
const handleEditDialogOpen = async () => {
  try {
    menuLoading.value = true;
    if (!editRoleInfo.roleId) {
      ElMessage.warning('角色ID不存在，请重新选择角色');
      return;
    }

    // 并行加载菜单列表和角色已选菜单
    const [menuRes, roleMenuRes] = await Promise.all([
      httpRequest.get('menu/list'),
      httpRequest.get(`menu/getMenusByRoleId?roleId=${editRoleInfo.roleId}`)
    ]);

    // 处理菜单数据
    allMenus.value = formatMenuData(menuRes.data);

    // 处理已选菜单ID并同步到表单
    const roleMenuIds = roleMenuRes.data?.menuIds || [];
    selectedMenuIds.value = Array.isArray(roleMenuIds) ? roleMenuIds : [];
    editRoleInfo.selectedMenuIds = [...selectedMenuIds.value];

  } catch (error) {
    console.error('加载菜单权限失败', error);
    ElMessage.error('加载菜单权限失败，请重试');
    allMenus.value = [];
    selectedMenuIds.value = [];
    editRoleInfo.selectedMenuIds = [];
  } finally {
    menuLoading.value = false;
  }
};

// 菜单勾选事件：实时同步选中状态到表单
const handleMenuCheck = () => {
  // 关键修复：通过树形菜单引用获取所有选中的ID
  const checkedIds = menuTreeRef.value.getCheckedKeys();
  // 同步到表单绑定字段（用于验证）
  editRoleInfo.selectedMenuIds = checkedIds;
  // 手动触发验证，实时更新表单状态
  editRoleFormRef.value?.validateField('selectedMenuIds');
};

// 更新角色及菜单权限
const updateRoleWithMenu = async () => {
  try {
    // 表单验证
    const valid = await editRoleFormRef.value.validate();
    if (!valid) return;

    // 更新角色基本信息
    await httpRequest.post('role/update', {
      roleId: editRoleInfo.roleId,
      roleName: editRoleInfo.roleName,
      roleCode: editRoleInfo.roleCode
    });

    // 保存菜单关联
    await httpRequest.post('role/saveMenuRelations', {
      roleId: editRoleInfo.roleId,
      menuIds: editRoleInfo.selectedMenuIds  // 使用表单同步的选中ID
    });

    ElMessage.success('角色及菜单权限更新成功');
    showEditDialog.value = false;
    await getAllRoles();
  } catch (error) {
    console.error('更新角色失败', error);
    ElMessage.error('更新角色失败，请重试');
  }
};

// 获取角色列表
const getAllRoles = async () => {
  try {
    loading.value = true;
    const res = await httpRequest.get('role/list');
    roleList.value = res.data || [];
    filteredRoleList.value = [...roleList.value];
  } catch (error) {
    console.error('获取角色列表失败', error);
    ElMessage.error('获取角色列表失败，请重试');
  } finally {
    loading.value = false;
  }
};

// 编辑角色
const editRole = (row) => {
  if (!row?.roleId) {
    ElMessage.warning('角色数据异常，请重试');
    return;
  }
  editRoleInfo.roleId = row.roleId;
  editRoleInfo.roleName = row.roleName || '';
  editRoleInfo.roleCode = row.roleCode || '';
  showEditDialog.value = true;
};

// 搜索角色
const handleSearch = () => {
  const search = searchValue.value.trim().toLowerCase();
  filteredRoleList.value = roleList.value.filter(item =>
      (item.roleName && item.roleName.toLowerCase().includes(search)) ||
      (item.roleCode && item.roleCode.toLowerCase().includes(search))
  );
};

// 添加角色
const addRole = async () => {
  try {
    const valid = await addRoleFormRef.value.validate();
    if (!valid) return;

    await httpRequest.post('role/add', addRoleInfo);
    ElMessage.success('角色添加成功');
    showAddDialog.value = false;
    addRoleInfo.roleName = '';
    addRoleInfo.roleCode = '';
    await getAllRoles();
  } catch (error) {
    console.error('添加角色失败', error);
    ElMessage.error('添加角色失败，请重试');
  }
};

// 处理删除确认
const handleDeleteConfirm = (roleId) => {
  deleteRoleId.value = roleId;
  showDeleteDialog.value = true;
};

// 执行删除
const deleteRole = async () => {
  try {
    await httpRequest.post('role/delete', { roleId: deleteRoleId.value });
    ElMessage.success('角色删除成功');
    showDeleteDialog.value = false;
    await getAllRoles();
  } catch (error) {
    console.error('删除角色失败', error);
    ElMessage.error('删除角色失败，请重试');
  }
};

// 打开添加对话框
const handleAddDialogOpen = () => {
  addRoleInfo.roleName = '';
  addRoleInfo.roleCode = '';
  if (addRoleFormRef.value) {
    addRoleFormRef.value.resetFields();
  }
};

// 表格行点击事件
const handleRowClick = (row) => {
  // 可选：行点击选中效果
};

// 页面初始化
onMounted(async () => {
  await getAllRoles();
});
</script>

<style scoped>
.role-manage-container {
  padding: 20px;
  background-color: #f5f6f8;
  min-height: calc(100vh - 110px);
  overflow: visible;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  flex-wrap: wrap;
  gap: 15px;
}

.menu-tree-container {
  border: 1px solid #ebeef5;
  border-radius: 4px;
  padding: 10px;
  margin-bottom: 10px;
  min-height: 200px;
}

.menu-tip {
  font-size: 12px;
  color: #666;
  line-height: 1.5;
}

.table-card {
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  border-radius: 4px;
  padding: 15px;
}

.empty-tip {
  padding: 50px 0;
  text-align: center;
}

.role-form {
  margin-top: 20px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
</style>
